#include "base/log.h"

#include <sys/stat.h>

#include <iostream>
#include "log.h"


// 设置日志等级
static rtc::LoggingSeverity get_log_severity(const std::string& level) {
    if ("verbose" == level) {
        return rtc::LS_VERBOSE;
    } else if ("info" == level) {
        return rtc::LS_INFO;
    } else if ("warning" == level) {
        return rtc::LS_WARNING;
    } else if ("error" == level) {
        return rtc::LS_ERROR;
    } else if ("none" == level) {
        return rtc::LS_NONE;
    }
    
    return rtc::LS_NONE;
}


// 初始化输出的日志
int xrtc::XrtcLog::init()
{
    // 在输出日志添加线程ID
    rtc::LogMessage::ConfigureLogging("thread tstamp");
    // 在输出日志添加文件前缀
    rtc::LogMessage::SetLogPathPrefix("/src");
    // 在输出日志添加日志等级
    rtc::LogMessage::AddLogToStream(this, get_log_severity(m_log_level));

    // 创建日志目录
    int ret = mkdir(m_log_dir.c_str(), 0755);
    if (ret != 0 && errno != EEXIST) {
        fprintf(stderr, "create log_dir[%s] failed\n", m_log_dir.c_str());
        return -1;
    }

    // 打开文件
    m_out_file.open(m_log_file_path, std::ios::app);
    if (!m_out_file.is_open()) {
        fprintf(stderr, "open log_file[%s] failed\n", m_log_file_path.c_str());
        return -1;
    }

    m_out_file_wf.open(m_log_file_wf, std::ios::app);
    if (!m_out_file_wf.is_open()) {
        fprintf(stderr, "open log_file_wf[%s] failed\n", m_log_file_wf.c_str());
        return -1;
    }

    return 0;
}

bool xrtc::XrtcLog::start()
{
    if (m_running) {
        fprintf(stderr, "log thread is running\n");
        return false;
    }

    m_running = true;

    m_log_thread.reset(new std::thread(&xrtc::XrtcLog::logThreadFunction, this));

    return true;
}

void xrtc::XrtcLog::stop()
{
    m_running = false;
    if (m_log_thread) {
        if (m_log_thread->joinable()) {
            m_log_thread->join();
            m_log_thread.reset();
        }
    }
}


// 等待日志写入线程结束
void xrtc::XrtcLog::join() 
{
    if (m_log_thread && m_log_thread->joinable()) { 
        m_log_thread->join();
    }
}

// 写入日志线程函数
void xrtc::XrtcLog::logThreadFunction()
{
    struct stat stat_data;
    std::stringstream ss;   

    while (m_running) {
        // 检查日志文件是否被删除或移动
        if (stat(m_log_file_path.c_str(), &stat_data) != 0) {
            m_out_file.close();
            m_out_file.open(m_log_file_path, std::ios::app);
        }

        if (stat(m_log_file_wf.c_str(), &stat_data) != 0) {
            m_out_file_wf.close();
            m_out_file_wf.open(m_log_file_wf, std::ios::app);
        }

        bool write_log = false;
        {
            std::lock_guard<std::mutex> lock(m_log_mutex);
            if (!m_log_queue.empty()) {
                write_log = true;
                // 写入日志
                while (!m_log_queue.empty()) {
                    ss << m_log_queue.front();
                    m_log_queue.pop();
                }
            }
        }

        if (write_log) {
            // 写入日志文件并主动刷盘
            m_out_file << ss.str();
            m_out_file.flush();
        }
        ss.str("");


        bool write_log_wf = false;
        {
            std::lock_guard<std::mutex> lock(m_log_mutex_wf);
            if (!m_log_queue_wf.empty()) {
                write_log_wf = true;
                // 写入日志
                while (!m_log_queue_wf.empty()) {
                    ss << m_log_queue_wf.front();
                    m_log_queue_wf.pop();
                }
            }
        }

        if (write_log_wf) {
            m_out_file_wf << ss.str();
            m_out_file_wf.flush();
        }
        ss.str("");


        std::this_thread::sleep_for(std::chrono::milliseconds(30));
    }
}

// 设置是否在控制台输出日志
void xrtc::XrtcLog::set_log_to_stderr(bool on)
{
    rtc::LogMessage::SetLogToStderr(on);
}

void xrtc::XrtcLog::OnLogMessage(const std::string &message, rtc::LoggingSeverity severity)
{
    // 错误日志
    if (severity >= rtc::WARNING) {
        std::lock_guard<std::mutex> lock(m_log_mutex_wf);
        m_log_queue_wf.push(message);
    } else {
    // 正常日志
        std::lock_guard<std::mutex> lock(m_log_mutex);
        m_log_queue.push(message);
    }
}

// 无实际意义无需实现
void xrtc::XrtcLog::OnLogMessage(const std::string & /* message */)
{
}
